package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.graphbuilder.math.func.MinFunction;
import com.jayway.jsonpath.JsonPath;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.commons.utils.Constants;
import com.ruoyi.system.commons.utils.OneMapVisionUtils;
import com.ruoyi.system.domain.FileModel;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.dto.*;
import com.ruoyi.system.mapper.QaDetailMapper;
import com.ruoyi.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.text.StringSubstitutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;


import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Auther Yulong Liu
 * @Date 2023/12/12 14:23
 * @Description
 **/

@Service
@Slf4j
public class QaDetailServiceImpl extends ServiceImpl<QaDetailMapper, QaDetailModel> implements QaDetailService{

    @Autowired
    private QaDetailMapper qaDetailMapper ;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private OneMapService oneMapService;

    @Autowired
    private ISysSourceRegistryService sysSourceRegistryService;

    @Autowired
    private PromptService promptService;

    @Autowired
    private ShotService shotService;

    @Autowired
    private ToolKitService toolKitService;

    @Autowired
    private FileService fileService;

    @Autowired
    private FileLibraryService fileLibraryService;


    /**@Description: 下面是大模型调用内部工具的服务方法
     */
    private final String BBEB_ASSISTANT_API = "http://10.1.79.76:6666/GPT/";

    private final String CHAT_MULTIBASE_API_URL = "http://10.1.79.85:7861/chat/knowledge_base_chat_multibase";

    private final String CHAT_GLM3_6B_API = "http://10.1.79.85:8848/v1/chat/completions";

    public MultibaseAnswerDto HandleMultibaseAnswers(MultibaseQueryDto userQuery){
        QaDetailModel records = new QaDetailModel();
        records.setSessionId(Long.parseLong(userQuery.getSessionId()));
        records.setUserId(SecurityUtils.getUserId());
        records.setQuestion(userQuery.getQuery());
        records.setGmtCreated(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

        List<String> kbNames = new ArrayList<>();
        for(Long id: userQuery.getKbIds()){
            LambdaQueryWrapper<FileLibraryModel> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(FileLibraryModel::getId,id);
            queryWrapper.eq(FileLibraryModel::getIsDeleted,0);
            FileLibraryModel fileLibraryModel = fileLibraryService.getOne(queryWrapper);
            kbNames.add(fileLibraryModel.getKbName());
        }
        userQuery.setKnowledge_base_names(kbNames);
        ////////////////////////////////////////////////////////////////
        String llmResultString = this.llmStartup(userQuery);
        System.out.println("+++++++++++++++++返回到的答案+++++++++++++++++++++++++++++++");
        System.out.println(llmResultString);
        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        //拆解llm_result_string
        MultibaseAnswerDto llmResult = JSON.parseObject(llmResultString,MultibaseAnswerDto.class);
        //因为这里没有session_id所以会被设置为默认值,所以要重新装载
        llmResult.setSessionId(userQuery.getSessionId());
        ////////////////////////////////////////////////////////////////
        records.setAnswer(llmResult.getAnswer());
        records.setGmtModified(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        records.setIsDeleted(0);
        records.setModelName(userQuery.getModelName());
        records.setPromptName(userQuery.getPromptName());
        records.setTemperature(userQuery.getTemperature());
        records.setKnowledgeBaseNames(userQuery.getKnowledge_base_names().toString());
        ////////////////////////////////////////////////////////////////
        //考虑入库的knowledgeSource的信息
        try{
            String docs = llmResult.getDocs();
            if (docs != null && docs.startsWith("[") && docs.endsWith("]")) {
                //json格式处理
                List<DocBriefInfoDto> docList = JSON.parseObject(docs, new TypeReference<List<DocBriefInfoDto>>() {
                });
                List<DocInfoDto> docInfoDtoList = JSON.parseObject(docs, new TypeReference<List<DocInfoDto>>() {});
                for (int i = 0 ; i < docList.size() ; i++) {
                    LambdaQueryWrapper<FileModel> queryWrapper = new LambdaQueryWrapper<FileModel>();
                    queryWrapper.eq(FileModel::getKbName,docList.get(i).getFile_name());
                    queryWrapper.eq(FileModel::getIsDeleted,0);
//                    FileModel finalFile = fileService.getOne(queryWrapper);
                    List<FileModel> fileList = fileService.list(queryWrapper); // 使用list()方法获取所有匹配结果列表
                    if (fileList != null){
                        FileModel finalFile = fileList.get(0); // 获取第一个匹配结果
                        String newFileName = finalFile.getFileName();
                        Long fileId = finalFile.getId();
                        docList.get(i).setFile_name(newFileName);
                        docList.get(i).setId(fileId);
                        docInfoDtoList.get(i).setFile_name(newFileName);
                        docInfoDtoList.get(i).setId(fileId);
                        log.info("name in view : {}",docList.get(i));
                    }
                }
                // Now docList contains your data
                docs = JSON.toJSONString(docList);
                llmResult.setDocs(JSON.toJSONString(docInfoDtoList));
            }
            records.setKnowledgeSource(docs);
        }catch (Exception e){
            log.info("parse error : " + e.getMessage());
        }

        //记录入库
//        this.save(records);

        return llmResult;
    }

    public String llmStartup(MultibaseQueryDto queryDto) {
        /**@Description: 调用chatglm大模型,做多文档库问答【不开放给用户】
         * @param [queryDto]
         * @return String
         */

        String ans = "";
        log.info("=========================进入请求接收体===============================");

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAccept(Arrays.asList(MediaType.TEXT_EVENT_STREAM));
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
//            log.info("=========================拼接消息===============================");

        try{
            String requestJson = JSON.toJSONString(queryDto);

//            ObjectMapper objectMapper = new ObjectMapper();
//            // 将 DTO 对象转换为 JSON 字符串
//            String requestJson = objectMapper.writeValueAsString(queryDto);
            log.info(requestJson);

            HttpEntity<String> requestEntity = new HttpEntity<>(requestJson, httpHeaders);

            log.info("=========================大模型，启动！===============================");
            ResponseEntity<String> responseEntity = restTemplate.exchange(URI.create(CHAT_MULTIBASE_API_URL),HttpMethod.POST,requestEntity,String.class);
            log.info(responseEntity.getBody());
            log.info("========================大模型答案 ↑↑↑===============================");
            ans = responseEntity.getBody();

        }catch (Exception e){
            log.info("json error: " + e.getMessage());
        }
        return ans;
    }

    @Override
    public List<HistoryBriefDto> listDetailByUserId(Long userId) {
        List<QaDetailModel> resultQaDetails = qaDetailMapper.listDetailByUserId(userId);
        List<HistoryBriefDto> historyBriefDtoList = new ArrayList<>();
        for (QaDetailModel tmp : resultQaDetails){
            historyBriefDtoList.add(new HistoryBriefDto(
                    tmp.getSessionId().toString(),
                    tmp.getGmtModified(),
                    tmp.getQuestion()
            ));
        }
        return historyBriefDtoList;
    }

    @Override
    public List<SessionHistoryDto> listSessionDetail(Long sessionId){
        return qaDetailMapper.listSessionDetail(sessionId);
    }

    @Override
    public Object mainLogic(MultibaseQueryDto multibaseQueryDto){
        /**@Description: 用户识别意图后生成解决方案的列表
         * @param [query]
         * @return List<JSONObject>
         */

        MockDto dto = new MockDto();
        //查询出所有的工具库信息
        List<ToolKit> toolKits = toolKitService.list();
        String target = this.intentRecognition(multibaseQueryDto.getQuery());
        log.info("target:{}",target);

        JSONObject intentionJson = JSONObject.parseObject(target);
        String intention = intentionJson.getString("问题类型");

        QaDetailModel record = new QaDetailModel();
        record.setIsDeleted(0);
        String timeNow = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        record.setGmtCreated(timeNow);
        record.setSessionId(Long.parseLong(multibaseQueryDto.getSessionId()));
        record.setQuestion(multibaseQueryDto.getQuery());
        record.setUserId(SecurityUtils.getUserId());
        record.setKnowledgeSource(multibaseQueryDto.getKnowledge_base_names() != null ? multibaseQueryDto.getKnowledge_base_names().toString():null);
        record.setPromptName(multibaseQueryDto.getPromptName());
        record.setModelName(multibaseQueryDto.getModelName());
        record.setTemperature(multibaseQueryDto.getTemperature());
        record.setGmtModified(timeNow);
        record.setMarkByHuman(0);

        MultibaseAnswerDto res = null;
        if (target.contains("检索查询")){
            res = this.handleWODMQuery(multibaseQueryDto,intention);
        }else if (target.contains("专题图")){
            if (target.contains("河流")){
                res = this.handleViewOneMapRiverQuery(multibaseQueryDto);
            }else {
                res = this.handleViewOneMapRswQuery(multibaseQueryDto);
            }

        }else if (target.contains("多模态图下载")){
            res = this.handleDownloadPicture(multibaseQueryDto);
        }
        else {
            res = this.HandleMultibaseAnswers(multibaseQueryDto);
        }

        record.setAnswer(res.getAnswer());
        this.save(record);
        res.setGmtCreated(timeNow);
        return res;
    }

    @Override
    public boolean markByHuman(MarkDto markDto) {
        LambdaUpdateWrapper<QaDetailModel> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(QaDetailModel::getSessionId,markDto.getSessionId());
        updateWrapper.eq(QaDetailModel::getGmtModified,markDto.getGmtModified());
        updateWrapper.set(QaDetailModel::getMarkByHuman,markDto.getMark());
        return this.update(updateWrapper);
    }


    private String intentRecognition(String query){
        String result = "none";

        MockDto dto = new MockDto();
        List<MessagesDto> tmp = new ArrayList<>();
        String prompt = promptService.assembleFirstPrompt();
        tmp.add(new MessagesDto("system", prompt));
        tmp.add(new MessagesDto("user",query));
        dto.setMessages(tmp);

        log.info("=========================进入请求接收体===============================");

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        log.info("=========================拼接消息===============================");
        String requestJson = JSON.toJSONString(dto);
        log.info("requestJson:{}",requestJson);

        HttpEntity<String> requestEntity = new HttpEntity<>(requestJson, httpHeaders);

        log.info("=========================大模型，启动！===============================");
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(URI.create(CHAT_GLM3_6B_API),HttpMethod.POST,requestEntity,JSONObject.class);
        log.info(String.valueOf(responseEntity.getBody()));
        log.info("========================大模型答案 ↑↑↑===============================");
        JSONObject ans = responseEntity.getBody();


        String content = this.getContent(ans);
        if (content != null){
            result = content;
        }


        return result;
    }


    /**
     * 轮询大模型
     * 先请求大模型，获取json
     * 随后请求第三方服务
     * @param solutionItems
     * {
     *     "工具调用": "水利对象筛选工具",
     *      "调用期望": "我需要找出中国的所有河流，按照河流长度降序排列"
     * }
     * @return
     */
    public Map<String,Object> requestExternalService(List<SolutionItem> solutionItems) throws ResourceAccessException{

        final String[] lastResult = {null};
        final String[] lastToolName = {null};
        final String[] lastIntention = {null};
        List<String> results = new ArrayList<>();

        solutionItems.forEach(solutionItem -> {

            //首先查出工具的信息 然后查出他的prop和shot
            String source = solutionItem.getSource();
            String query = solutionItem.getQuery();

            SysSourceRegistry externalTool = sysSourceRegistryService.selectExistSysSourceRegistryByName(source);
            PromptModel promptModel = new PromptModel();
            promptModel.setPtContent(externalTool.getToolPrompt());
            List<ShotModel> shotModels = shotService.queryShotsByTName(externalTool.getResourceName());

            if (lastResult[0] != null) {
                String resultPrompt = promptService.assembleResultPrompt(lastToolName[0], lastIntention[0], lastResult[0]);
                promptModel.setResultPrompt(resultPrompt);
            }


            //首先请求一次大模型获取本轮请求的json

            log.info("========================对大模型发起外部工具请求参数查询===============================");
            String requestParamJson = this.getQueryJson(externalTool, promptModel, shotModels, query);

            log.info("========================读取配置文件===============================");
            //这里当前默认是读取json文件
            String jsonFileUrl = externalTool.getJsonFileUrl();
//            String[] split = jsonFileUrl.split("/");
//            StringBuilder urlBuilder = new StringBuilder();
//            for (String s : split) {
//                urlBuilder.append(s).append("\\");
//            }
//            String fileUrl = urlBuilder.substring(0, urlBuilder.length() - 1);
            String content = null;
            JSONObject requestParam = null;
            //完成参数替换
            ResponseEntity<String> result = null;
            try {
                log.info("jsonFile路径：{}", jsonFileUrl);
//                content = new String(Files.readAllBytes(Paths.get(jsonFileUrl)));
                content = restTemplate.getForEntity(jsonFileUrl, String.class).getBody();
                JSONObject rootJson = JSONObject.parseObject(content);
                // 从这里开始区分GET方法和POST方法
                String requestType = rootJson.getString("request_type");
                // 处理GET请求
                if (requestType.equals("GET")) {
                    JSONObject paramsJson = rootJson.getJSONObject("params");
                    JSONArray requiredJson = paramsJson.getJSONArray("required");
                    Map<String, String> replaceMap = new HashMap<>();
                    requiredJson.forEach(item -> {
                        String paramPath = ((JSONObject) item).getString("paramPath");
                        String paramName = ((JSONObject) item).getString("paramName");
                        String paramValue = JsonPath.read(requestParamJson, paramPath);

                        replaceMap.put(paramName, paramValue);
                    });
                    String propertiesUrl = JsonPath.read(content, "$.params.properties_url");
                    StringSubstitutor sub = new StringSubstitutor(replaceMap);
                    // 替换后生成了一个带有参数的get请求url
                    String url = sub.replace(propertiesUrl);

                    log.info("========================外部工具请求json===============================");
                    log.info("外部工具请求json:{}", requestParamJson);
                    log.info("实际发送请求url:{}", url);

                    JSONObject headers = rootJson.getJSONObject("headers");
                    HttpHeaders httpHeaders = new HttpHeaders();
                    if (headers.getString("token") != null && !Objects.equals(headers.getString("token"), "")){
                        String token = headers.getString("token"); // 从 Headers 对象中获取 token
                        httpHeaders.set("token", token); // 将 token 设置到 HttpHeaders 中
                    }
                    HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders); // 创建 HttpEntity，包含 headers
                    //发起请求
                    result = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);

                // 处理POST请求
                } else if (requestType.equals("POST")) {
                    JSONObject bodyJson = rootJson.getJSONObject("body");
                    JSONArray requiredJson = bodyJson.getJSONArray("required");
                    Map<String, String> replaceMap = new HashMap<>();
                    requiredJson.forEach(item -> {
                        String paramPath = ((JSONObject) item).getString("paramPath");
                        String paramName = ((JSONObject) item).getString("paramName");
                        String paramValue = JsonPath.read(requestParamJson, paramPath);

                        replaceMap.put(paramName, paramValue);
                    });
                    String propertiesJson = JsonPath.read(content, "$.body.properties_json");
                    StringSubstitutor sub = new StringSubstitutor(replaceMap);
                    String resolvedString = sub.replace(propertiesJson);

                    requestParam = JSONObject.parseObject(resolvedString);

                    log.info("========================外部工具请求json===============================");
                    log.info("外部工具请求json:{}", requestParamJson);
                    log.info("实际发送请求json:{}", requestParam);

                    String url = externalTool.getServiceUrl();
                    Map<String, Object> paramsMap = requestParam.toJavaObject(Map.class);

                    //判断请求参数的发送方式
                    JSONObject headers = rootJson.getJSONObject("headers");
                    String contentType = headers.getString("Content-Type");

                    if (contentType.equals("application/json")){
                        // application/json内容的处理方式
                        HttpHeaders httpHeaders = new HttpHeaders();
                        // 判断是否需要添加token
                        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
                        if (headers.getString("token") != null && !Objects.equals(headers.getString("token"), "")){
                            String token = headers.getString("token"); // 从 Headers 对象中获取 token
                            httpHeaders.set("token", token); // 将 token 设置到 HttpHeaders 中
                        }
                        HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(paramsMap, httpHeaders);
                        //发起请求
                        result = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);

                    } else if (contentType.equals("multipart/form-data")) {
                        // multipart/form-data内容的处理方式
                        // 获取在properties_json中写好的固定参数
                        for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
                            replaceMap.put(entry.getKey(), entry.getValue().toString());
                        }

                        // 创建 MultiValueMap 并添加参数
                        MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
                        for (Map.Entry<String, String> entry : replaceMap.entrySet()) {
                            body.add(entry.getKey(), entry.getValue());
                        }
                        log.info("表单参数:{}",body);
                        HttpHeaders httpHeaders = new HttpHeaders();
                        httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
                        if (headers.getString("token") != null && !Objects.equals(headers.getString("token"), "")){
                            String token = headers.getString("token"); // 从 Headers 对象中获取 token
                            httpHeaders.set("token", token); // 将 token 设置到 HttpHeaders 中
                        }
                        HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(body, httpHeaders);
                        //发起请求
                        result = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
                    }


                }

            } catch (Exception e) {
                e.printStackTrace();
            }

            //获取第三方工具的结果，用于下一轮去向大模型去提问
            //添加校验，如果第三方工具出现问题，需要终止流程
            lastResult[0] = result.getBody();
            lastToolName[0] = externalTool.getResourceName();
            lastIntention[0] = query;
            results.add(result.getBody());
            String resultMessage = result.getBody();
            if (resultMessage.length() > Constants.MAX_TOKEN) {
                resultMessage = resultMessage.substring(0, Math.toIntExact(Constants.MAX_TOKEN)) + "...[truncated]";
            }
            log.info("工具请求结果：{}", resultMessage);

            if (lastResult[0] != null) {
                JSONObject lastResultJson = JSONObject.parseObject(lastResult[0]);
                if (lastResultJson.containsKey("responseCD")) {
                    String responseCD = lastResultJson.getString("responseCD");
                    if (!responseCD.equals("1")) {
                        String msg = "访问失败，可能是由于第三方服务不稳定导致，请检查提问内容，稍等片刻后再提问";
                        if (lastResultJson.containsKey("responseMsg")) {
                            msg = lastResultJson.getString("responseMsg");
                        }
                        throw new ServiceException(msg);
                    }
                }
            }
        });


        Map<String,Object> map = new HashMap<>();
        map.put("results",results);
        map.put("toolName",solutionItems.get(solutionItems.size()-1).getSource());

        return map;
    }

    /**
     * 写死的一张图服务
     * @return
     */
    public String requestExternalService(){
        String waterObject = oneMapService.getWaterObject();
        String waterObjectDetail = oneMapService.getWaterObjectDetail();
        return waterObjectDetail;
    }


    private String getContent(JSONObject json){
        String result = null;
        try{
            JSONArray choices = json.getJSONArray("choices");
            if (choices == null || choices.isEmpty()) {
                choices = new JSONArray();
                choices.add(new JSONObject());
            }
            JSONObject firstChoice = choices.getJSONObject(0);
            JSONObject message = firstChoice.getJSONObject("message");
            if (message == null) {
                message = new JSONObject();
            }
            String content = message.getString("content");
            if (content == null) {
                content = "";
            }//content就是一个json的array
            result = content;
        }catch (Exception e) {
            log.error("Error parsing json: " +e);
        }

        return result;
    }


    private String getMessage(JSONObject json){
        String result = null;
        try{
            JSONArray choices = json.getJSONArray("choices");
            if (choices == null || choices.isEmpty()) {
                choices = new JSONArray();
                choices.add(new JSONObject());
            }
            JSONObject firstChoice = choices.getJSONObject(0);
            String message = firstChoice.getString("message");
            result = message;
        }catch (Exception e) {
            log.error("Error parsing json: " +e);
        }

        return result;
    }


    /**
     * 一张图的llm交互逻辑
     * @param userQuery
     * @return
     */
    private MultibaseAnswerDto handleWODMQuery(MultibaseQueryDto userQuery,String intention){

//        intention = intention.substring(0,intention.length()-2);

        //获取大模型的解决方案
        MockDto dto = new MockDto();
        String query = userQuery.getQuery();

        List<MessagesDto> queryList = new ArrayList<>();
        ToolKit toolkit = toolKitService.getToolkitByTkName(intention);
        List<SysSourceRegistry> tools = sysSourceRegistryService.getToolByTkName(toolkit.getTkName());
        List<ShotModel> shotModels = shotService.queryShotsByTName(toolkit.getTkName());
        //TODO 这里也需要进行拼接
        queryList.add(new MessagesDto("system",toolkit.getTkPrompt()));
        shotModels.forEach(shotModel -> {
            queryList.add(new MessagesDto("user",shotModel.getStQueryInput()));
            queryList.add(new MessagesDto("assistant",shotModel.getStExpectedOutput()));
        });
        queryList.add(new MessagesDto("user",query));

        dto.setMessages(queryList);

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);

        log.info("=========================拼接消息===============================");
        String requestJson = JSON.toJSONString(dto);
        log.info("requestJson:{}",requestJson);

        HttpEntity<String> requestEntity = new HttpEntity<>(requestJson, httpHeaders);

        log.info("=========================大模型，启动！===============================");
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(URI.create(CHAT_GLM3_6B_API),HttpMethod.POST,requestEntity,JSONObject.class);
        log.info(String.valueOf(responseEntity.getBody()));
        log.info("========================大模型答案 ↑↑↑===============================");
        JSONObject ans = responseEntity.getBody();
        String solution = this.getMessage(ans);

        JSONObject totalResult = JSONObject.parseObject(solution);
        JSONArray solutionJsonArray = new JSONArray();
        if (totalResult.containsKey("content")){
            try {
                String contentString = totalResult.getString("content");
                Object content = JSON.parse(contentString);

                if (content instanceof JSONArray) {
                    solutionJsonArray = (JSONArray) content;
                } else if (content instanceof JSONObject) {
                    solutionJsonArray = new JSONArray();
                    solutionJsonArray.add((JSONObject) content);
                }

//                solutionJsonArray = totalResult.getJSONArray("content");
            }catch (JSONException e){
                e.printStackTrace();
                MultibaseAnswerDto res = new MultibaseAnswerDto();
                res.setSessionId(userQuery.getSessionId());
                res.setAnswer(totalResult.getString("content"));
                return res;
            }
        }
        // 由于大模型可能会返回“问题类型”，暂时用一下代码进行处理
        for (int i = 0; i < solutionJsonArray.size(); i++) {
            JSONObject jsonObject = solutionJsonArray.getJSONObject(i);
            if (jsonObject.containsKey("问题类型")) {
                String value = jsonObject.getString("问题类型");
                jsonObject.remove("问题类型");
                jsonObject.put("工具调用", value);
            }
        }

        List<SolutionItem> solutions = solutionJsonArray.stream().map(item -> {
            JSONObject jsonObject = (JSONObject) item;
            SolutionItem solutionItem = jsonObject.toJavaObject(SolutionItem.class);
            return solutionItem;
        }).collect(Collectors.toList());

        log.info("========================方案获取完毕！===============================");

        log.info("========================开始轮询LLM！===============================");
        List<String> externalResults = null;
        String lastToolName = null;
        Map<String,Object> resultMap = new HashMap<>();
        try {
            resultMap = this.requestExternalService(solutions);
            externalResults = (List<String>) resultMap.get("results");
            lastToolName = (String) resultMap.get("toolName");
        }catch (ServiceException e){
            log.error(e.getDetailMessage(),e);
            MultibaseAnswerDto res = new MultibaseAnswerDto();
            res.setJsonResult(null);
            res.setSessionId(userQuery.getSessionId());
            res.setAnswer(e.getMessage());
            return res;
        }catch (ResourceAccessException e){
            log.error(e.getMessage(),e);
            MultibaseAnswerDto res = new MultibaseAnswerDto();
            res.setJsonResult(null);
            res.setSessionId(userQuery.getSessionId());
            res.setAnswer("连接超时！");
            userQuery.setKbIds(Arrays.asList(1L));
            log.info("跳转进入知识库");
            return this.HandleMultibaseAnswers(userQuery);
//            return res;
        }

        log.info("========================轮询LLM结束！===============================");

        //由大模型汇总答案，需要此时的query格式和prompt
//        this.queryLLM()
        //这里先暂时自己写一个回答来
        SolutionItem lastSolution = solutions.get(solutions.size() - 1);
        String type = null;
        if (lastSolution.getSource().contains("名录")){
            type = "列表";
            if (lastSolution.getSource().contains("河流")){
                type = "河流列表";
            } else if (lastSolution.getSource().contains("水库")) {
                type = "水库列表";
            }
        }else if (lastSolution.getSource().contains("详情")){
            type = "详情";
            if (lastSolution.getSource().contains("河流")){
                type = "河流详情";
            } else if (lastSolution.getSource().contains("水库")) {
                type = "水库详情";
            } else if (lastSolution.getSource().contains("水闸")) {
                type = "水闸详情";
            } else if (lastSolution.getSource().contains("泵站")) {
                type = "泵站详情";
            }
        }

//        String result = promptService.assembleResultPrompt(solutions.get(solutions.size() - 1).getSource(), intention, externalResults.get(externalResults.size() - 1));
        String result = "";
        if (externalResults.get(externalResults.size()-1).length() > Constants.MAX_TOKEN){
            result = "返回结果过多，请在多模态界面查看结果。";
        }else {
            result = promptService.assembleRIPrompt(toolkit.getTkName(),query,lastToolName,externalResults.get(externalResults.size()-1));
        }
        log.info("LLMResult:{}",result);
        MultibaseAnswerDto res = new MultibaseAnswerDto();
        // 增加一个临时的对河流和水库详情查询的返回值的处理，使其转变为更适合前端展示的格式
        String rawResult = externalResults.get(externalResults.size()-1);
        String attributes = result2Pretty(rawResult, lastSolution.getSource());
        res.setJsonResult(attributes);
        res.setSessionId(userQuery.getSessionId());
        res.setAnswer(result);
        res.setType(type);
        return res;
    }

    /**
     * 请求大模型
     * @param messages 封装好，格式化好的用户提问信息
     * @return
     */
    public String queryLLM(List<MessagesDto> messages){
        String result = null;

        MockDto dto = new MockDto();

        dto.setMessages(messages);

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);

        log.info("=========================拼接消息===============================");
        String requestJson = JSON.toJSONString(dto);
        log.info("requestJson:{}",requestJson);


        HttpEntity<String> requestEntity = new HttpEntity<>(requestJson, httpHeaders);

        log.info("=========================大模型，启动！===============================");
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(URI.create(CHAT_GLM3_6B_API),HttpMethod.POST,requestEntity,JSONObject.class);
        log.info(String.valueOf(responseEntity.getBody()));
        log.info("========================大模型答案 ↑↑↑===============================");
        JSONObject ans = responseEntity.getBody();


        String content = this.getContent(ans);
        if (content != null){
            result = content;
        }

        return result;
    }


    /**
     * 请求大模型获取请求第三方的json
     * @param tool
     * @param promptModel
     * @param shotModels
     * @return
     */
    public String getQueryJson(SysSourceRegistry tool,PromptModel promptModel,List<ShotModel> shotModels,String query){
        List<MessagesDto> messages = new ArrayList<>();
        messages.add(new MessagesDto("system", promptModel.getPtContent()));
        shotModels.forEach(shotModel -> {
            messages.add(new MessagesDto("user",shotModel.getStQueryInput()));
            messages.add(new MessagesDto("assistant",shotModel.getStExpectedOutput()));
        });
        if (promptModel.getResultPrompt() != null){
            messages.add(new MessagesDto("user",query+promptModel.getResultPrompt()));
        }else {
            messages.add(new MessagesDto("user",query));
        }


        String res = this.queryLLM(messages);
        return res;
    }

    /**
     * 替换prompt
     * @param valueMap
     * @param prompt
     * @return
     */
    private String replacePrompt(Map<String,String> valueMap,PromptModel prompt){
        StringSubstitutor sub = new StringSubstitutor(valueMap);
        String resolvedString = sub.replace(prompt.getPtContent());
        prompt.setPtContent(resolvedString);
        return resolvedString;
    }

    private String jsonPathArrayGet(int index){
        StringBuilder builder = new StringBuilder();
        builder.append("$.body.required[").append(index).append("].paramPath");
        return builder.toString();
    }

    private MultibaseAnswerDto handleViewOneMapRiverQuery(MultibaseQueryDto userQuery){
        //获取大模型的解决方案
        MockDto dto = new MockDto();
        String query = userQuery.getQuery();

        List<MessagesDto> queryList = new ArrayList<>();
        queryList.add(new MessagesDto("system", Constants.VIEW_ONEMAP_RIVER_PROMPT));
        queryList.add(new MessagesDto("user","将长江展示到图上"));
        queryList.add(new MessagesDto("assistant","{\"河流编码\":\"\", \"河流名称\":\"长江\"}"));
        queryList.add(new MessagesDto("user","将秦淮河展示到图上"));
        queryList.add(new MessagesDto("assistant","{\"河流编码\":\"\", \"河流名称\":\"秦淮河\"}"));
        queryList.add(new MessagesDto("user","将河流代码为CC000000000S的河流展示到图上"));
        queryList.add(new MessagesDto("assistant","{\"河流编码\":\"CC000000000S\", \"河流名称\":\"\"}"));
        queryList.add(new MessagesDto("user","将河流代码为CC000000020S的河流展示到图上"));
        queryList.add(new MessagesDto("assistant","{\"河流编码\":\"CC000000020S\", \"河流名称\":\"\"}"));
        queryList.add(new MessagesDto("user","将长江、黄河展示到图上"));
        queryList.add(new MessagesDto("assistant","{\"河流编码\":\"\", \"河流名称\":\"长江,黄河\"}"));
        queryList.add(new MessagesDto("user",query));

        dto.setMessages(queryList);

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);

        log.info("=========================拼接消息===============================");
        String requestJson = JSON.toJSONString(dto);
        log.info("requestJson:{}",requestJson);

        HttpEntity<String> requestEntity = new HttpEntity<>(requestJson, httpHeaders);

        log.info("=========================大模型，启动！===============================");
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(URI.create(CHAT_GLM3_6B_API),HttpMethod.POST,requestEntity,JSONObject.class);
        log.info(String.valueOf(responseEntity.getBody()));
        log.info("========================大模型答案 ↑↑↑===============================");
        JSONObject ans = responseEntity.getBody();
        String solution = this.getMessage(ans);

        JSONObject totalResult = JSONObject.parseObject(solution);
        String contentResult = totalResult.getString("content");  // 获取"content"

        log.info("========================结果拼接===============================");
        String finalShot = OneMapVisionUtils.decorationViewOneMapRiverQuery(contentResult);
        log.info("========================结果拼接结果！===============================");

        String type = "专题图河流";
        String result = "大模型关于"+type+"的结果请在一张图上查看！";
        MultibaseAnswerDto res = new MultibaseAnswerDto();
        res.setJsonResult(finalShot);//等一下填入返回给前端的内容
        res.setSessionId(userQuery.getSessionId());
        res.setAnswer(result);
        res.setType(type);
        return res;
    }

//    private String decorationViewOneMapRswQuery(String riverJson){
//        /**@Description: 将接收到的参数翻译成前端想要的结果
//         * @param [riverJson]
//         * @return java.lang.String
//         */
////        String riverJson = "{ \"河流编码\": \"123\", \"河流名称\": \"长江\" }";
//        String filterJsonRswb = "";
//        String filterJsonDam = "";
//
//
//
//
//
//        log.info("接收到的的json:{}",riverJson);
//        JSONObject riverObject = JSON.parseObject(riverJson);
//        JSONObject filterFinal = JSON.parseObject(filterJson);
//        JSONArray filterArray = filterFinal.getJSONArray("filterOptions").getJSONObject(0).getJSONArray("filters");
////        log.info("filterArray{}",filterFinal.toString());
////        log.info("拆解了什么东西{}",filterArray.toString());
////        JSONArray filterArray = JSON.parseArray(filterJson);
//
//        for (int i = 0; i < filterArray.size(); i++) {
//            JSONObject filterObject = filterArray.getJSONObject(i);
//            String filterKey = filterObject.getString("filterKey");
//
//            if (riverObject.containsKey(filterKey)) {
//                String value = riverObject.getString(filterKey);
//                filterObject.put("value", value);
//            }
//        }
//        filterFinal.getJSONArray("filterOptions").getJSONObject(0).put("filters", filterArray);
////        System.out.println(filterFinal.toJSONString());
//        log.info("发送出去的json:{}",filterFinal.toJSONString());
//        return filterFinal.toJSONString();
//    }


    private MultibaseAnswerDto handleViewOneMapRswQuery(MultibaseQueryDto userQuery){
        MockDto dto = new MockDto();
        String query = userQuery.getQuery();

        List<MessagesDto> queryList = new ArrayList<>();
        queryList.add(new MessagesDto("system", Constants.VIEW_ONEMAP_RSW_PROMPT));
        queryList.add(new MessagesDto("user","将幸福水库展示到图上"));
        queryList.add(new MessagesDto("assistant","{\"水库编码\":\"\", \"水库名称\":\"幸福水库\"}"));
        queryList.add(new MessagesDto("user","将怀柔水库和密云水库展示到图上"));
        queryList.add(new MessagesDto("assistant","{\"水库编码\":\"\", \"水库名称\":\"怀柔水库,密云水库\"}"));
        queryList.add(new MessagesDto("user","将小浪底水库展示到图上"));
        queryList.add(new MessagesDto("assistant","{\"水库编码\":\"\", \"水库名称\":\"小浪底水库\"}"));
        queryList.add(new MessagesDto("user","将水库编码为CS001S的水库展示到图上"));
        queryList.add(new MessagesDto("assistant","{\"水库编码\":\"CS001S\", \"水库名称\":\"\"}"));
        queryList.add(new MessagesDto("user",query));

//        queryList.add(new MessagesDto("assistant","{\"水库编码\":\"\", \"水库名称\":\"幸福水库\",\"工程规模\":\"\"}"));
//        queryList.add(new MessagesDto("user","将大一型的王村水库展示到图上"));
//        queryList.add(new MessagesDto("assistant","{\"水库编码\":\"\", \"水库名称\":\"王村水库\",\"工程规模\":\"大一型\"}"));
//        queryList.add(new MessagesDto("user","将怀柔水库和密云水库展示到图上"));
//        queryList.add(new MessagesDto("assistant","{\"水库编码\":\"\", \"水库名称\":\"怀柔水库,密云水库\",\"工程规模\":\"\"}"));
//        queryList.add(new MessagesDto("user","将小一型的水库展示到图上"));
//        queryList.add(new MessagesDto("assistant","{\"水库编码\":\"\", \"水库名称\":\"\",\"工程规模\":\"小一型\"}"));
//        queryList.add(new MessagesDto("user","将大二型和小一型的水库展示到图上"));
//        queryList.add(new MessagesDto("assistant","{\"水库编码\":\"\", \"水库名称\":\"\",\"工程规模\":\"大二型,小一型\"}"));


        dto.setMessages(queryList);

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);

        log.info("=========================拼接消息===============================");
        String requestJson = JSON.toJSONString(dto);
        log.info("requestJson:{}",requestJson);

        HttpEntity<String> requestEntity = new HttpEntity<>(requestJson, httpHeaders);

        log.info("=========================大模型，启动！===============================");
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(URI.create(CHAT_GLM3_6B_API),HttpMethod.POST,requestEntity,JSONObject.class);
        log.info(String.valueOf(responseEntity.getBody()));
        log.info("========================大模型答案 ↑↑↑===============================");
        JSONObject ans = responseEntity.getBody();
        String solution = this.getMessage(ans);

        JSONObject totalResult = JSONObject.parseObject(solution);
        String contentResult = totalResult.getString("content");  // 获取"content"

        log.info("========================结果拼接===============================");
        String finalShot = OneMapVisionUtils.decorationViewOneMapRswbQuery(contentResult);

        log.info("========================结果拼接结果！===============================");

        String type = "专题图水库";
        String result = "大模型关于"+type+"的结果请在一张图上查看！";
        MultibaseAnswerDto res = new MultibaseAnswerDto();
        res.setJsonResult(finalShot);//等一下填入返回给前端的内容
        res.setSessionId(userQuery.getSessionId());
        res.setAnswer(result);
        res.setType(type);
        return res;

    }

    private MultibaseAnswerDto handleDownloadPicture(MultibaseQueryDto userQuery){
        String type = "下载";
        String result = "大模型关于"+type+"的结果请接收！";
        MultibaseAnswerDto res = new MultibaseAnswerDto();
        res.setJsonResult("{\"type\":\"screenshot\",\"data\":{\"isContainerBase\":true}}");
        res.setSessionId(userQuery.getSessionId());
        res.setAnswer(result);
        res.setType(type);

        return res;
    }

    /**
     * 把json结果转换为{paramName:xxx,paramValue:xxx}的格式
     * @param rawResult
     * @return
     */
    private String result2Pretty(String rawResult, String toolName){

        JSONObject jsonObject = JSONObject.parseObject(rawResult);
        JSONArray resultArray = new JSONArray();
        JSONArray finalJson = new JSONArray();
        // 针对各自的返回结果格式进行返回值的清理
        if (toolName.equals("河流详情信息查询")) {
            HashMap<Object, Object> riverMap = new HashMap<>();
            riverMap.put("NAME","名称");
            riverMap.put("SOURCE","数据来源");
            riverMap.put("FSTNAME","所属河流");
            riverMap.put("NAME2","别名");
            resultArray = jsonObject.getJSONArray("features");

            for (int i = 0; i < resultArray.size(); i++) {
                JSONObject element = resultArray.getJSONObject(i);
                JSONObject attributes = element.getJSONObject("attributes");
                JSONArray oneRiver = new JSONArray();
                for (Map.Entry<String, Object> entry : attributes.entrySet()) {
                    JSONObject newObject = new JSONObject();
                    if (riverMap.get(entry.getKey()) != null){
                        newObject.put("name", riverMap.get(entry.getKey()));
                        if(entry.getValue() == null) {
                            newObject.put("value", "null");
                        }else {
                            newObject.put("value", entry.getValue());
                        }
                        oneRiver.add(newObject);
                    }

                }
                JSONObject geometry = new JSONObject();
                geometry.put("name", "geometry");
                geometry.put("value", element.getJSONObject("geometry"));
                oneRiver.add(geometry);
                finalJson.add(oneRiver);
            }
        } else if (toolName.equals("水库详情信息查询")) {
            HashMap<Object, Object> RRMap = new HashMap<>();
            RRMap.put("resCode","水库代码");
            RRMap.put("resName","名称");
            RRMap.put("resType","类型");
            RRMap.put("uppLevFlco","防洪高水位");
            RRMap.put("deadLev","死水位 单位：m");
            RRMap.put("totCap","总库容 单位：10⁴m³");
            RRMap.put("benResCap","兴利库容 单位：10⁴m³");
            RRMap.put("lowLeftLong","longitude");
            RRMap.put("lowLeftLat","latitude");
            RRMap.put("startDate","开工时间");
            RRMap.put("compDate","建成时间");
            RRMap.put("effDate","记录生效时间");
            resultArray = jsonObject.getJSONArray("data");
//            for (int i = 0; i < jsonArray.size(); i++) {
//                JSONObject dataObject = jsonArray.getJSONObject(i);
//                if ("RR".equals(dataObject.getString("sttp"))) {
//                    resultArray.add(dataObject);
//                }
//            }
            HashMap<Object, Object> typeMap = new HashMap<>();
            typeMap.put("A","大型");
            typeMap.put("B","中型");
            typeMap.put("C","小一型");
            typeMap.put("D","小二型");
            for (int i = 0; i < resultArray.size(); i++) {
                JSONObject element = resultArray.getJSONObject(i);
                JSONArray oneRR = new JSONArray();
                for (Map.Entry<String, Object> entry : element.entrySet()) {
                    JSONObject newObject = new JSONObject();
                    if (RRMap.get(entry.getKey()) != null){
                        newObject.put("name", RRMap.get(entry.getKey()));
                        if(entry.getValue() == null) {
                            newObject.put("value", "null");
                        }else {
                            // 针对类型代码的转换
                            if (RRMap.get(entry.getKey()).equals("类型")){
                                newObject.put("value", typeMap.get(entry.getValue()));

                            }else {
                                newObject.put("value", entry.getValue());
                            }
                        }
                        oneRR.add(newObject);
                    }

                }
                finalJson.add(oneRR);
            }
        } else if (toolName.equals("水闸详情信息查询")) {
            HashMap<Object, Object> wageMap = new HashMap<>();
            wageMap.put("wagaCode","水闸代码");
            wageMap.put("wagaName","名称");
            wageMap.put("wagaType","类型");
            wageMap.put("desLockDisc","设计最大过闸流量 单位：m³/s");
            wageMap.put("gaorNum","闸孔数量 单位：孔");
            wageMap.put("startLong","longitude");
            wageMap.put("startLat","latitude");
            wageMap.put("effDate","记录生效时间");
            resultArray = jsonObject.getJSONArray("data");
//            for (int i = 0; i < jsonArray.size(); i++) {
//                JSONObject dataObject = jsonArray.getJSONObject(i);
//                if ("RR".equals(dataObject.getString("sttp"))) {
//                    resultArray.add(dataObject);
//                }
//            }
            HashMap<Object, Object> typeMap = new HashMap<>();
            typeMap.put("A","大型");
            typeMap.put("B","中型");
            typeMap.put("C","小一型");
            typeMap.put("D","小二型");
            for (int i = 0; i < resultArray.size(); i++) {
                JSONObject element = resultArray.getJSONObject(i);
                JSONArray oneRR = new JSONArray();
                for (Map.Entry<String, Object> entry : element.entrySet()) {
                    JSONObject newObject = new JSONObject();
                    if (wageMap.get(entry.getKey()) != null){
                        newObject.put("name", wageMap.get(entry.getKey()));
                        if(entry.getValue() == null) {
                            newObject.put("value", "null");
                        }else {
                            // 针对类型代码的转换
                            if (wageMap.get(entry.getKey()).equals("类型")){
                                newObject.put("value", typeMap.get(entry.getValue()));

                            }else {
                                newObject.put("value", entry.getValue());
                            }
                        }
                        oneRR.add(newObject);
                    }

                }
                finalJson.add(oneRR);
            }
        } else if (toolName.equals("泵站详情信息查询")) {
            HashMap<Object, Object> pustMap = new HashMap<>();
            pustMap.put("pustCode","泵站代码");
            pustMap.put("pustName","名称");
            pustMap.put("pustType","类型");
            pustMap.put("insFlow","装机流量 单位：m³/s");
            pustMap.put("insPow","装机功率 单位：kW");
            pustMap.put("pustLong","longitude");
            pustMap.put("pustLat","latitude");
            pustMap.put("pumpNum","水泵数量 单位：台");
            pustMap.put("pustLoc","泵站所在位置");
            pustMap.put("effDate","记录生效时间");
            resultArray = jsonObject.getJSONArray("data");
//            for (int i = 0; i < jsonArray.size(); i++) {
//                JSONObject dataObject = jsonArray.getJSONObject(i);
//                if ("RR".equals(dataObject.getString("sttp"))) {
//                    resultArray.add(dataObject);
//                }
//            }
            HashMap<Object, Object> typeMap = new HashMap<>();
            typeMap.put("A","大一型");
            typeMap.put("B","中型");
            typeMap.put("C","小一型");
            typeMap.put("D","小二型");
            for (int i = 0; i < resultArray.size(); i++) {
                JSONObject element = resultArray.getJSONObject(i);
                JSONArray oneRR = new JSONArray();
                for (Map.Entry<String, Object> entry : element.entrySet()) {
                    JSONObject newObject = new JSONObject();
                    if (pustMap.get(entry.getKey()) != null){
                        newObject.put("name", pustMap.get(entry.getKey()));
                        if(entry.getValue() == null) {
                            newObject.put("value", "null");
                        }else {
                            // 针对类型代码的转换
                            if (pustMap.get(entry.getKey()).equals("类型")){
                                newObject.put("value", typeMap.get(entry.getValue()));

                            }else {
                                newObject.put("value", entry.getValue());
                            }
                        }
                        oneRR.add(newObject);
                    }

                }
                finalJson.add(oneRR);
            }
        } else {
            return rawResult;
        }

        return finalJson.toString();



    }

}
